import * as Layout from './demo-src/layout'
import BN from 'bn.js'
import * as BufferLayout from 'buffer-layout'
import { createProgramAccountIfNotExist, createTokenAccountIfNotExist, sendTransaction } from '@/utils/web3'
import { Account, Connection, Transaction, PublicKey, TransactionInstruction } from '@solana/web3.js'
import { AccountLayout, Token, TOKEN_PROGRAM_ID } from '@solana/spl-token'

// import { TokenSwap, TOKEN_SWAP_PROGRAM_ID } from './demo-src'

const PUBLIC_KEY = '5LokBV2RCRVJFb5d4gFGehVvNCoHwYvo9u8wLkZHDrVd'

export class Numberu64 extends BN {
  /**
   * Convert to Buffer representation
   */
  toBuffer(): Buffer {
    const a = super.toArray().reverse()
    const b = Buffer.from(a)
    if (b.length === 8) {
      return b
    }

    const zeroPad = Buffer.alloc(8)
    b.copy(zeroPad)
    return zeroPad
  }

  /**
   * Construct a Numberu64 from Buffer representation
   */
  // @ts-ignore
  static fromBuffer(buffer): BN {
    return new BN(
      [...buffer]
        .reverse()
        .map((i) => `00${i.toString(16)}`.slice(-2))
        .join(''),
      16
    )
  }
}

export async function createNToken(connection: Connection, wallet: any): Promise<any> {
  const transaction = new Transaction()

  const keys = [] as any
  const commandDataLayout = BufferLayout.struct([BufferLayout.u8('instruction')])
  let data = Buffer.alloc(1024)
  {
    const encodeLength = commandDataLayout.encode(
      {
        instruction: 6 // CreateNToken
      },
      data
    )
    data = data.slice(0, encodeLength)
  }
  const programId = new PublicKey(PUBLIC_KEY)
  transaction.add(
    new TransactionInstruction({
      keys,
      programId,
      data
    })
  )
  return await sendTransaction(connection, wallet, transaction, [])
}

export async function supply(connection: Connection, wallet: any): Promise<any> {
  const transaction = new Transaction()
  const amount = 100
  const keys = [] as any
  const commandDataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('amount')])
  let data = Buffer.alloc(1024)
  {
    const encodeLength = commandDataLayout.encode(
      {
        instruction: 7,
        amount: new Numberu64(amount.toString()).toBuffer()
      },
      data
    )
    data = data.slice(0, encodeLength)
  }
  const programId = new PublicKey(PUBLIC_KEY)
  transaction.add(
    new TransactionInstruction({
      keys,
      programId,
      data
    })
  )
  return await sendTransaction(connection, wallet, transaction, [])
}

export async function borrow(connection: Connection, wallet: any): Promise<any> {
  const transaction = new Transaction()
  const amount = 100
  const keys = [] as any
  const commandDataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('amount')])
  let data = Buffer.alloc(1024)
  {
    const encodeLength = commandDataLayout.encode(
      {
        instruction: 8,
        amount: new Numberu64(amount.toString()).toBuffer()
      },
      data
    )
    data = data.slice(0, encodeLength)
  }
  const programId = new PublicKey(PUBLIC_KEY)
  transaction.add(
    new TransactionInstruction({
      keys,
      programId,
      data
    })
  )
  return await sendTransaction(connection, wallet, transaction, [])
}

export async function payBorrow(connection: Connection, wallet: any): Promise<any> {
  const transaction = new Transaction()
  const amount = 100
  const keys = [] as any
  const commandDataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('amount')])
  let data = Buffer.alloc(1024)
  {
    const encodeLength = commandDataLayout.encode(
      {
        instruction: 9,
        amount: new Numberu64(amount.toString()).toBuffer()
      },
      data
    )
    data = data.slice(0, encodeLength)
  }
  const programId = new PublicKey(PUBLIC_KEY)
  transaction.add(
    new TransactionInstruction({
      keys,
      programId,
      data
    })
  )
  return await sendTransaction(connection, wallet, transaction, [])
}

export async function stake(connection: Connection, wallet: any): Promise<any> {
  const transaction = new Transaction()
  const amount = 100

  const keys = [] as any
  const commandDataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('amount')])
  let data = Buffer.alloc(1024)
  {
    const encodeLength = commandDataLayout.encode(
      {
        instruction: 10,
        amount: new Numberu64(amount.toString()).toBuffer()
      },
      data
    )
    data = data.slice(0, encodeLength)
  }
  const programId = new PublicKey(PUBLIC_KEY)
  transaction.add(
    new TransactionInstruction({
      keys,
      programId,
      data
    })
  )
  return await sendTransaction(connection, wallet, transaction, [])
}

export async function unstake(connection: Connection, wallet: any): Promise<any> {
  const transaction = new Transaction()
  const amount = 100

  const keys = [] as any
  const commandDataLayout = BufferLayout.struct([BufferLayout.u8('instruction'), Layout.uint64('amount')])
  let data = Buffer.alloc(1024)
  {
    const encodeLength = commandDataLayout.encode(
      {
        instruction: 11,
        amount: new Numberu64(amount.toString()).toBuffer()
      },
      data
    )
    data = data.slice(0, encodeLength)
  }
  const programId = new PublicKey(PUBLIC_KEY)
  transaction.add(
    new TransactionInstruction({
      keys,
      programId,
      data
    })
  )
  return await sendTransaction(connection, wallet, transaction, [])
}
